package org.comet.auxiliary.client.auto.palm;

        import com.google.common.util.concurrent.ThreadFactoryBuilder;
        import org.comet.auxiliary.client.liaobei.util.LapuUtil;
        import org.comet.auxiliary.client.liaobei.util.SystemModel;
        import org.comet.auxiliary.common.UserInfo;
        import org.comet.auxiliary.common.exception.WrongPasswordException;
        import org.comet.auxiliary.common.handler.func.AbstractSaveNewFunctionHandler;
        import org.comet.auxiliary.common.handler.func.DataCallback;
        import org.comet.auxiliary.common.handler.soft.SoftHandler;
        import org.comet.auxiliary.common.swing.SwingHelper;
        import org.comet.auxiliary.common.util.*;
        import org.comet.auxiliary.common.util.config.ClientConfigHelper;

        import java.util.*;
        import java.util.concurrent.*;

/**
 * @author wq
 * @date 2019/10/8
 * @description 发包功能实现
 */
public class PalmFunctionHandler extends AbstractSaveNewFunctionHandler {
    /**
     * 定时任务池, 轮询待领取的红包
     */
    private static ScheduledExecutorService takePacketPool;
    /**
     * 红包编号池, 避免重复添加红包
     */
    private static ConcurrentHashMap<String, Boolean> packetTnoSet = new ConcurrentHashMap<>(16);
    /**
     * 待领取红包
     */
    private static ConcurrentHashMap<String, Map<String, Object>> packetMap = new ConcurrentHashMap<>(16);
    /**
     * 待检测红包
     */
    private static ConcurrentHashMap<String, Map<String, Object>> checkPacketMap = new ConcurrentHashMap<>(16);
    /**
     * 软件层对象池
     */
    private static ConcurrentHashMap<String, SoftHandler> userSoftHandler = new ConcurrentHashMap<>(16);

    private SoftHandler softHandler;
    /**
     * 以下都是, 读取配置, 分别为:
     * 可领取的群 ID
     * 是否开启了先抢 N 包
     * 是否开启了后抢 N 包
     * 先抢 N 包 N 的值
     * 后抢 N 包 N 的值
     * 探测 ID
     * 领取频率
     */
    public PalmFunctionHandler(SoftHandler softHandler) {
        this.softHandler = softHandler;
        String loginUserPhone = "";
        Object loginUser = softHandler.getLoginUser();
        if (loginUser instanceof UserInfo) {
            UserInfo userInfo = (UserInfo) loginUser;
            SystemModel.userInfos.add(userInfo);
            loginUserPhone = userInfo.getPhone();
        }
        userSoftHandler.put(loginUserPhone, softHandler);
//        ThreadUtil.executeByCommon(()->{
//        SystemModel.userSoftHandler = userSoftHandler;
            doRunPacketDeque();
//        });
    }

    private static String getTakeRid() {
        return ClientConfigHelper.getConfig().getString("rid");
    }

    private static Boolean firstSomeOn() {
        return ClientConfigHelper.getConfig().getBoolean("firstSomeOn");
    }

    private static Boolean lastSomeOn() {
        return ClientConfigHelper.getConfig().getBoolean("lastSomeOn");
    }

    private static String getFirstSomeCount() {
        return ClientConfigHelper.getConfig().getString("firstSomeCount");
    }

    private static String getLastSomeCount() {
        return ClientConfigHelper.getConfig().getString("lastSomeCount");
    }

    private static String getProbeId() {
        return ClientConfigHelper.getConfig().getString("probeId");
    }

    private static float takeSleep() {
        MapBean config = ClientConfigHelper.getConfig();
        if (config.containsKey("takeSleep")) {
            return Float.parseFloat(config.getString("takeSleep"));
        } else {
            return 1.0f;
        }
    }
    /**
     * 遍历检测池, 用于判断先抢后抢所需的条件
     */
    private static synchronized void doRunCheckPacketDeque() {
        takePacketPool.scheduleWithFixedDelay(() -> {
            if (checkPacketMap.isEmpty()) {
                return;
            }
            System.out.println("foreach check:: " + checkPacketMap.size());
            for (Map.Entry<String, Map<String, Object>> mapEntry : checkPacketMap.entrySet()) {
                String tno = mapEntry.getKey();
                Map<String, Object> packet = mapEntry.getValue();
                System.out.println("out check :: " + checkPacketMap.size());
                ThreadUtil.executeByCommon(() -> {
                    check0(tno, packet);
                });
            }
        }, 100, 500, TimeUnit.MILLISECONDS);
    }
    /**
     * 遍历待领取红包, 一一领取
     */
    private static synchronized void doRunPacketDeque() {
        System.out.println("ThreadId："+Thread.currentThread().getId()+"ThreadName："+Thread.currentThread().getName());

        System.out.println("== in doRunPacketDeque");
        if (takePacketPool != null) {
            return;
        }
        System.out.println("== into doRunPacketDeque");
        ThreadFactory threadFactory = (new ThreadFactoryBuilder()).setNameFormat("take-packet-schedule-%d").build();
        takePacketPool = new ScheduledThreadPoolExecutor(Integer.MAX_VALUE, threadFactory, new ThreadPoolExecutor.AbortPolicy());

        doRunCheckPacketDeque();
        takePacketPool.scheduleWithFixedDelay(() -> {
            if (!packetMap.isEmpty()) {
                System.out.println("foreach deque:: " + packetMap.size());
                for (Map.Entry<String, Map<String, Object>> mapEntry : packetMap.entrySet()) {
                    String key = mapEntry.getKey();
                    Map<String, Object> data = mapEntry.getValue();
                    System.out.println("out deque :: " + packetMap.size());
                    try {
//                        if (takeSleep() > 90) {
//                            Thread.sleep((long) (takeSleep()));
//                        }
                        Thread.sleep(1);
                    } catch (InterruptedException ignored) {
                    }
                    packetMap.remove(key);
                    // 遍历登录的软件层们, 一一领取
                        System.out.println("ThreadId："+Thread.currentThread().getId()+"ThreadName："+Thread.currentThread().getName());
                    String redId = (String) data.get("objectId");
                    List<UserInfo> userInfos = SystemModel.userInfos;
                    for (UserInfo userInfo : userInfos){
                        ThreadUtil.executeByCommon(()->{
                            try {
                                take0(userInfo, redId, 0);
//                                LapuUtil.takePacket(userInfo.getTk(), userInfo.getUid(), redId);
//                                String s = LapuUtil.takePacket(userInfo.getTk(), userInfo.getUid(), redId);
//                                System.out.println(s);
                            }catch (Exception e){
                                e.printStackTrace();
                            }
                        });
                    }





//                        Collection<SoftHandler> softHandlers = userSoftHandler.values();
//                        int i = 0;

//                        for (SoftHandler softHandler : softHandlers) {
//                            boolean last =false;
//                            if (i++ == softHandlers.size() - 1) {
//                                last = true;
//                            }


//                    ThreadUtil.executeByCommon(() -> {
//                                take0(softHandler, data, 0);
//                            });
//                            if (last) {
//                                DataCallback sendLast = softHandler.getFunctionHandler().getCallback("sendLast");
//                                if (sendLast != null) {
//                                    MapBean mapBean = new MapBean();
//                                    mapBean.putAll(data);
//                                    sendLast.callback(mapBean);
//                                }
//                            }
//                        }

//                    ThreadUtil.executeByCommon(() -> {
//                        long start = System.currentTimeMillis();
//                        CountDownLatch countDownLatch = new CountDownLatch(softHandlers.size());
//
//                        try {
//                            countDownLatch.await();
//                        } catch (InterruptedException e) {
//                            e.printStackTrace();
//                        }
//                        long end = System.currentTimeMillis();
//                        double seconds = (end - start) / 1000d;
//                        System.out.println("== take all packet need time :: " + seconds);
//                    });
                }
            }
        }, 100, 200, TimeUnit.MILLISECONDS);
    }
    /**
     * 获取探测号所属的软件层对象
     */
    public static SoftHandler getTakeSoftHandler() {
        String probeId = getProbeId();
        if (StringUtil.isBlank(probeId)) {
            return null;
        }
        return userSoftHandler.get(probeId);
    }
    /**
     * 判断探测号是否领取, 检测红包领取情况, 根据配置判断是否满足条件, 满足则加入领取队列
     */
    private static void check0(String tno, Map<String, Object> data) {
        try {
            SoftHandler softHandler = (SoftHandler) data.get("softHandler");
            if (softHandler == null) {
                return;
            }
            // 判断探测号是否有领取红包
            if (!data.containsKey("firstTake")) {
                SoftHandler takeSoftHandler = getTakeSoftHandler();
                ThreadUtil.executeByCommon(()->{
                    take0((UserInfo) softHandler.getLoginUser(), (String) data.get("objectId"), 0);
                });
                data.put("firstTake", true);
            }
            // 获取红包领取个数用于判断
            String packetRes = softHandler.queryPacket0(data);
            Map<String, Object> res = JsonUtils.getMap(packetRes);
            String status = res.getOrDefault("resultCode", "").toString();
            if ("1".equals(status) || "0".equals(status)) {
                res = (Map<String, Object>) res.get("data");
                if (res == null) {
                    return;
                }
                Map<String, Object> packet = (Map<String, Object>) res.get("packet");
                if (packet == null) {
                    return;
                }
                List<Map<String, Object>> list = (List<Map<String, Object>>) res.get("list");
                if (list == null) {
                    return;
                }
                String giftQuantity = packet.getOrDefault("count", "0").toString();
                String yesGetGift = packet.getOrDefault("receiveCount", "0").toString();

                int count = Integer.parseInt(giftQuantity);
                int getCount = Integer.parseInt(yesGetGift);

                boolean canDo;
                if (firstSomeOn()) {
                    String firstSomeCount = getFirstSomeCount();
                    int some = Integer.parseInt(firstSomeCount);
                    canDo = getCount >= some;
                } else {
                    String lastSome = getLastSomeCount();
                    int some = Integer.parseInt(lastSome);
                    canDo = count - getCount <= some;
                }

                if (canDo) {
                    System.err.println("== packet check over:: packet can do! == :: ");
                    packetMap.put(tno, data);
                    checkPacketMap.remove(tno);
                }
            }
        } catch (Exception e) {
            String message = e.getMessage();
            e.printStackTrace();
            System.err.println("== check packet error :: " + message);
        }
    }

    private static int inputCount = 0;

    public static void main(String[] args) {
        while (true){
            inputCount++;
            if (inputCount == SystemModel.loginCount){
                inputCount = 0;
                System.out.println(inputCount);
            }
        }
    }

    /**
     * 调用接口领取红包
     */
    private static void take0(UserInfo softHandler, String redId, int retry) {
        System.out.println("===== take0 data ====="+redId);
        System.out.println("ThreadId："+Thread.currentThread().getId()+"ThreadName："+Thread.currentThread().getName());

        try {
            if (softHandler == null) {
                return;
            }
            long start = System.currentTimeMillis();
            LapuUtil.takePacket(softHandler.getTk(), softHandler.getUid(), redId);

//            softHandler.takePacket(data);
//            int takeAmt = 0;
//            String packetAmtFen = (String) data.get("packetAmtFen");
//            if (!StringUtil.isBlank(packetAmtFen)) {
//                takeAmt = Integer.parseInt(packetAmtFen);
//            } else {
//                Integer takeAmtFen = softHandler.queryPacket(data);
//                if (takeAmtFen != null) {
//                    takeAmt = takeAmtFen;
//                    PacketCountHelper.addTotalTakeAmt(takeAmtFen);
//                    PacketCountHelper.addTotalTakeCount(1);
//                }
//            }
            long end = System.currentTimeMillis();
            double seconds = (end - start) / 1000d;
            inputCount++;
            //判断已登录的人是否都领取了红包
            if (inputCount == SystemModel.loginCount){
                inputCount = 0;
//                String takeAmtFen = softHandler.queryPacket0(data);
                String takeAmtFen = LapuUtil.queryPacket(softHandler.getTk(), redId, softHandler.getUid());
                Map<String, Object> takeAmtFenMap = JsonUtils.getMap(takeAmtFen);
                int resultCode = (int) takeAmtFenMap.get("resultCode");
                if (resultCode == 0){
                    Map<String, Object> dataMap = (Map<String, Object>) takeAmtFenMap.get("data");
                    ArrayList<Map<String,Object>> list = (ArrayList<Map<String, Object>>) dataMap.get("list");
                    Iterator<Map<String, Object>> iterator = list.iterator();
                    while (iterator.hasNext()){
                        Map<String, Object> next = iterator.next();
                        double money = (double) next.get("money");
                        SwingHelper.addLog("TAKE_RELATION_PACKET_TIP", NumberUtil.toFixed(money));
                    }
                }
//                if (takeAmtFen != null) {
//                    takeAmt = takeAmtFen;
//                    PacketCountHelper.addTotalTakeAmt(takeAmtFen);
//                    PacketCountHelper.addTotalTakeCount(1);
//                }
//                SwingHelper.addLog("TAKE_RELATION_PACKET_TIP", NumberUtil.toFixed(takeAmt / 100d));
            }
        } catch (WrongPasswordException pass) {
            String message = pass.getMessage();
            if (!"3".equals(message)) {
                if (message.contains("权限验证失败")) {
                    if (retry > 2) {
                        System.err.println("=== take packet error, after retry :: " + message);
                        return;
                    }
                    take0(softHandler, redId, retry + 1);
                } else {
                    System.err.println("=== take packet error :: " + message);
                }
            } else {
                System.err.println("has take");
            }
        } catch (Exception e) {
            String message = e.getMessage();
            if (retry > 2) {
                System.err.println("=== take packet exception :: " + message);
                e.printStackTrace();
                return;
            }
            take0(softHandler, redId, retry + 1);
        }
    }



//    /**
//     * 调用接口领取红包
//     */
//    private static void take0(SoftHandler softHandler, Map<String, Object> data, int retry) {
//        System.out.println("===== take0 data ====="+data);
//        System.out.println("ThreadId："+Thread.currentThread().getId()+"ThreadName："+Thread.currentThread().getName());
//
//        try {
//            if (softHandler == null) {
//                return;
//            }
//            long start = System.currentTimeMillis();
//            softHandler.takePacket(data);
////            int takeAmt = 0;
////            String packetAmtFen = (String) data.get("packetAmtFen");
////            if (!StringUtil.isBlank(packetAmtFen)) {
////                takeAmt = Integer.parseInt(packetAmtFen);
////            } else {
////                Integer takeAmtFen = softHandler.queryPacket(data);
////                if (takeAmtFen != null) {
////                    takeAmt = takeAmtFen;
////                    PacketCountHelper.addTotalTakeAmt(takeAmtFen);
////                    PacketCountHelper.addTotalTakeCount(1);
////                }
////            }
//            long end = System.currentTimeMillis();
//            double seconds = (end - start) / 1000d;
//            inputCount++;
//            //判断已登录的人是否都领取了红包
//            if (inputCount == SystemModel.loginCount){
//                inputCount = 0;
//                String takeAmtFen = softHandler.queryPacket0(data);
//                Map<String, Object> takeAmtFenMap = JsonUtils.getMap(takeAmtFen);
//                int resultCode = (int) takeAmtFenMap.get("resultCode");
//                if (resultCode == 0){
//                    Map<String, Object> dataMap = (Map<String, Object>) takeAmtFenMap.get("data");
//                    ArrayList<Map<String,Object>> list = (ArrayList<Map<String, Object>>) dataMap.get("list");
//                    Iterator<Map<String, Object>> iterator = list.iterator();
//                    while (iterator.hasNext()){
//                        Map<String, Object> next = iterator.next();
//                        double money = (double) next.get("money");
//                        SwingHelper.addLog("TAKE_RELATION_PACKET_TIP", NumberUtil.toFixed(money));
//                    }
//                }
////                if (takeAmtFen != null) {
////                    takeAmt = takeAmtFen;
////                    PacketCountHelper.addTotalTakeAmt(takeAmtFen);
////                    PacketCountHelper.addTotalTakeCount(1);
////                }
////                SwingHelper.addLog("TAKE_RELATION_PACKET_TIP", NumberUtil.toFixed(takeAmt / 100d));
//            }
//        } catch (WrongPasswordException pass) {
//            String message = pass.getMessage();
//            if (!"3".equals(message)) {
//                if (message.contains("权限验证失败")) {
//                    if (retry > 2) {
//                        System.err.println("=== take packet error, after retry :: " + message);
//                        return;
//                    }
//                    take0(softHandler, data, retry + 1);
//                } else {
//                    System.err.println("=== take packet error :: " + message);
//                }
//            } else {
//                System.err.println("has take");
//            }
//        } catch (Exception e) {
//            String message = e.getMessage();
//            if (retry > 2) {
//                System.err.println("=== take packet exception :: " + message);
//                e.printStackTrace();
//                return;
//            }
//            take0(softHandler, data, retry + 1);
//        }
//    }

    private boolean takePacket() {
        return true;
    }

    private boolean takeRPacket() {
        return true;
    }
    /**
     * 一下都是读取配置, 分别是:
     * 只领取的用户ID
     * 是否领取所有群聊红包
     * 是否领取所有私聊红包
     */
    private String getTakeUid() {
        return ClientConfigHelper.getConfig().getString("uid");
    }

    private Boolean ridOn() {
        return ClientConfigHelper.getConfig().getBoolean("ridOn");
    }

    private Boolean uidOn() {
        return ClientConfigHelper.getConfig().getBoolean("uidOn");
    }
    /**
     * 判断是否开始抢包
     */
    private boolean isNotWork() {
        // default is false
        MapBean config = ClientConfigHelper.getConfig();
        if (config.containsKey("__work")) {
            return "0".equals(config.get("__work").toString());
        }
        return false;
    }

    @Override
    public void dealPrivateTextMsg(String text, String sendId, String toId, Map<String, Object> data) throws Exception {
        if (isNotWork()) {
            return;
        }
        boolean sendByMe = softHandler.getLoginUserId().equals(sendId);
        if (sendByMe && "getid".equals(text)) {
            softHandler.sendTextMsgToPrivate("对方id：" + toId, toId);
        }
    }

    @Override
    public void dealRelationTextMsg(String text, String sendId, String rId, Map<String, Object> data) throws Exception {
        if (isNotWork()) {
            return;
        }
        if ("rid".equals(text)) {
            softHandler.sendTextMsgToPrivate("[群id]：" + rId, null, true);
        }
        if ("tr".equals(text)) {
            softHandler.sendTextMsgToRelation("[PALM]", rId);
        }
        if ("tm".equals(text)) {
            softHandler.sendTextMsgToRelation("[RUNNING]", rId);
        }
    }

    @Override
    public SoftHandler getSoftHandler() {
        return softHandler;
    }

    private void addLog(String log, Object... params) {
        SwingHelper.addLog(log, params);
    }

    /**
     * 收到私聊红包消息, 判断是否可领取
     */
    @Override
    public void dealPrivatePacketMsg(String packetText, Integer packetAmtFen, String sendId, String toId, Map<String, Object> data) throws Exception {
        if (isNotWork()) {
            return;
        }
        String loginUserId = softHandler.getLoginUserId();
        String sessionKey = sendId + "-" + toId;
        if (takePacket()) {
            if (data.containsKey("action_contact_red_Return")) {
                return;
            }
            if (toId.equals(loginUserId)) {
                boolean sendIdInTakeUid = getTakeUid().contains(sendId);
                if (uidOn() || sendIdInTakeUid) {
                    Object loginUser = softHandler.getLoginUser();
                    if (loginUser instanceof UserInfo) {
                        UserInfo userInfo = (UserInfo) loginUser;
                        String phone = userInfo.getPhone();
                        data.put("phone", phone);
                    }
                    data.put("to", sendId);
                    data.put("chat", "chat");
                    addToDeque(data);
                    PacketCountHelper.addSessionTakeAmt(sessionKey, packetAmtFen);
                    PacketCountHelper.addSessionTakeCount(sessionKey, 1);
                }
            }
        }
        PacketCountHelper.addSessionReadAmt(sessionKey, packetAmtFen);
        PacketCountHelper.addSessionReadCount(sessionKey, 1);
    }

    /**
     * 收到群聊红包, 判断是否可领取, 根据配置判断是进入检测队列还是直接领取
     */
    @Override
    public void dealRelationPacketMsg(String packetText, Integer packetAmtFen, String sendId, String toId, Map<String, Object> data) throws Exception {
        System.out.println("===XML Thread===  ThreadId："+Thread.currentThread().getId()+"      ThreadName："+Thread.currentThread().getName());
        if (isNotWork()) {
            return;
        }
        String loginUserPhone = "";
        Object loginUser = softHandler.getLoginUser();
        if (loginUser instanceof UserInfo) {
            UserInfo userInfo = (UserInfo) loginUser;
            loginUserPhone = userInfo.getPhone();
        }

        String loginUserId = softHandler.getLoginUserId();
        boolean sendByMe = loginUserId.equals(sendId);
        if (!sendByMe && takeRPacket()) {
            boolean ridInTakeRids = getTakeRid().contains(toId);
            if (ridOn() || ridInTakeRids) {
                data.put("phone", loginUserPhone);
                data.put("to", toId);
                data.put("chat", "groupchat");

                boolean hasSome = firstSomeOn() || lastSomeOn();
                if (hasSome && ridInTakeRids) {
                    addToCheck(data);
                } else {
                    addToDeque(data);
                }
            }
        }
    }
    /**
     * 将红包加入领取队列
     */
    private void addToDeque(Map<String, Object> data) {
        String tno = data.get("objectId").toString();
        if (packetTnoSet.containsKey(tno)) {
            return;
        }
        packetTnoSet.put(tno, true);
        data.put("softHandler", softHandler);
        packetMap.put(tno, data);
        System.out.println("== addToDeque :: " + tno);
    }
    /**
     * 将红包加入检测队列
     */
    private void addToCheck(Map<String, Object> data) {
        String tno = data.get("objectId").toString();
        data.put("softHandler", softHandler);
        checkPacketMap.put(tno, data);
    }

    @Override
    public void destroy() throws Exception {
//        packetDeque.clear();
//        takePacketPool.shutdownNow();
    }
}
